//Blur bingo a point
function mosaicBlurBingo(mosaic, p, fn, area){
	area = area || 1;
	for(var i = 1; i <= area; i++){
		if(mosaic.some(function(a){
			return fn(a.weight) > 0
				&& (a.x == p.x + i || a.x == p.x - i || a.x == p.x)
				&& (a.y == p.y + i || a.y == p.y - i || a.y == p.y)
		})) return true;
	}
	return false;
}
//Compair 2 mosaic array, and cal score
function compairMosaic(sys, user){
	var i = 0, len = sys.length;
	var cal = 0, sum = 0;
	var unbingo = [];
	for(; i < len; i++){
		sum += sys[i].weight;
		if(sys[i].weight > 0){
			if(user[i].weight > 0 || mosaicBlurBingo(user, sys[i], function(w){ return w > 0; })){
				continue;
			} else {
				cal += sys[i].weight;
			}
		} else if(user[i].weight > 0 && mosaicBlurBingo(sys, user[i], function(w){ return w > 0; })){
			cal += user[i].weight * user[i].weight;
			unbingo.push([0, user[i]]);
		} else {
			cal += user[i].weight;
			user[i].weight > 0 && unbingo.push([1, user[i]]);
		}
	}
	var score = Math.min(1, Math.max(0, 1 - cal / sum));
	// score = Math.sqrt(score);
	return { score: score, lost: unbingo };
}
//Get mosaic array from canvas-context
function getMosaic(ctx, blockSize){
	var pixes = [];
	ImageDataHelper.eachBlock(ctx, function(img, x, y){
		var c = 0, len = img.data.length / 4;
		ImageDataHelper.eachData(img.data, function(color){
			if(color[3] > 0){
				c += 1;
			}
		});
		pixes.push({ x: x, y: y, weight: c / len })
	}, blockSize);

	return pixes;
}
//Draw mosaic block into canvas
function drawMosaic(mosaic, ctx, blockSize, color, alpha){
	color = color || '0,0,0';
	alpha = alpha || 0;
	mosaic.forEach(function(p){
		if(p.weight > 0){
			ctx.beginPath();
			ctx.rect(p.x * blockSize, p.y * blockSize, blockSize, blockSize);
			ctx.fillStyle = 'rgba(' + color + ',' + (alpha || p.weight) + ')';
			// ctx.fillStyle = 'rgba(0,0,0,0.3)';
			ctx.fill();
		}
	});
}